// +build mage

package main

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps
	"github.com/magefile/mage/sh"
)

const packageName = "dragonfly"

var goexe = "go"

func init() {
	if exe := os.Getenv("GOEXE"); exe != "" {
		goexe = exe
	}
}

func flagEnv() map[string]string {
	return map[string]string{
		"HTTP_PROXY":  "192.168.80.1:1080",
		"HTTPS_PROXY": "192.168.80.1:1080",
	}
}

func getDep() error {
	return sh.Run(goexe, "get", "-u", "github.com/golang/dep/cmd/dep")
}

// Build dragonfly binary
func Build() error {
	mg.Deps(Vendor)
	fmt.Println("Building...")
	cmd := exec.Command("go", "build", "-o", "dragonfly", ".")
	return cmd.Run()
}

// Install dragonfly product
func Install() error {
	mg.Deps(Build)
	fmt.Println("Installing...")
	return os.Rename("./dragonfly", "/usr/local/bin/dragonfly")
}

// Install Go Dep and sync vendored dependencies
func Vendor() error {
	mg.Deps(getDep)
	fmt.Println("Installing Deps...")
	return sh.RunWith(flagEnv(), "dep", "ensure", "-v", "-update")
}

// Remove built product
func Clean() {
	fmt.Println("Cleaning...")
	cmd := exec.Command("go", "clean", "./...")
	cmd.Run()
}

// Run gofmt linter
func Fmt() error {
	if !isGoLatest() {
		return nil
	}
	pkgs, err := dragonflyPkgs()
	if err != nil {
		return err
	}
	failed := false
	first := true
	for _, pkg := range pkgs {
		files, err := filepath.Glob(filepath.Join(pkg, "*.go"))
		if err != nil {
			return nil
		}
		for _, f := range files {
			// gofmt doesn't exit with non-zero when it finds unformatted code
			// so we have to explicitly look for output, and if we find any, we
			// should fail this target.
			s, err := sh.Output("gofmt", "-l", f)
			if err != nil {
				fmt.Printf("ERROR: running gofmt on %q: %v\n", f, err)
				failed = true
			}
			if s != "" {
				if first {
					fmt.Println("The following files are not gofmt'ed:")
					first = false
				}
				failed = true
				fmt.Println(s)
			}
		}
	}
	if failed {
		return errors.New("improperly formatted go files")
	}
	return nil
}

func dragonflyPkgs() ([]string, error) {
	mg.Deps(getDep)
	s, err := sh.Output(goexe, "list", "./...")
	if err != nil {
		return nil, err
	}
	pkgs := strings.Split(s, "\n")
	pkgPrefixLen := len(packageName)
	for i := range pkgs {
		pkgs[i] = "." + pkgs[i][pkgPrefixLen:]
	}
	return pkgs, nil
}

func isGoLatest() bool {
	return strings.Contains(runtime.Version(), "1.10")
}
